package main

import (
	"os"
	"bytes"
	"archive/zip"
	"fmt"
	"io"
)

func Compress(from, to string) error {
	src, err := os.Open(from)
	if err != nil {
		return err
	}

	buffOut := new(bytes.Buffer)
	w := zip.NewWriter(buffOut)

	if err = compress(src, "", w); err != nil {
		return err
	}

	src.Close()
	w.Close()

	destination, err := os.Create(to)
	if err != nil {
		return err
	}

	_, err = buffOut.WriteTo(destination)
	if err != nil {
		return err
	}

	return nil
}

func CompressToBytes(from string) ([]byte, error) {
	src, err := os.Open(from)
	if err != nil {
		return nil, err
	}

	buffOut := new(bytes.Buffer)
	w := zip.NewWriter(buffOut)

	if err = compress(src, "", w); err != nil {
		return nil, err
	}

	src.Close()
	w.Close()

	return buffOut.Bytes(), nil
}

func compress(file *os.File, prefix string, zw *zip.Writer) error {
	info, err := file.Stat()
	if err != nil {
		return err
	}
	if info.IsDir() {
		prefix = prefix + info.Name() + "/"
		fileInfoList, err := file.Readdir(-1)
		if err != nil {
			return err
		}
		zw.Create(prefix)
		for _, fi := range fileInfoList {
			f, err := os.Open(file.Name() + "/" + fi.Name())
			fmt.Println("file name: ", file.Name()+"/"+fi.Name())
			if err != nil {
				fmt.Println(err)
				return err
			}
			err = compress(f, prefix, zw)
			if err != nil {
				return err
			}
			f.Close()
		}
	} else {
		fd, err := zw.Create(prefix + info.Name())
		fmt.Println(prefix + info.Name())
		if err != nil {
			return err
		}
		buffIn := new(bytes.Buffer)
		_, err = buffIn.ReadFrom(file)
		if err != nil {
			return err
		}
		fd.Write(buffIn.Bytes())
	}
	return nil
}

func Decompress(from string) error {
	reader, err := zip.OpenReader(from)
	defer reader.Close()
	if err != nil {
		return err
	}

	for k, v := range reader.File {
		fmt.Println(k, v.Name, v.FileInfo().IsDir())
		if v.FileInfo().IsDir() {
			if err := os.MkdirAll(v.Name, 0666); err != nil {
				return err
			}

		} else {
			reader, err := v.Open()
			if err != nil {
				return err
			}

			fd, err := os.Create(v.Name)
			if err != nil {
				return err
			}

			_, err = io.Copy(fd, reader)
			if err != nil {
				return err
			}

			reader.Close()
		}
	}
	return nil
}

//func DecompressFromBytes(from []byte) error {
//	bufIn := new(bytes.Buffer)
//	_, err := bufIn.Read(from)
//	if err != nil {
//		return err
//	}
//
//	reader, err := zip.OpenReader()
//	defer reader.Close()
//	if err != nil {
//		return err
//	}
//	for k, v := range reader.File {
//		fmt.Println(k, v.Name, v.FileInfo().IsDir())
//		if v.FileInfo().IsDir() {
//			if err := os.MkdirAll(v.Name, 0666); err != nil {
//				return err
//			}
//		} else {
//			reader, err := v.Open()
//			if err != nil {
//				return err
//			}
//			fd, err := os.Create(v.Name)
//			if err != nil {
//				return err
//			}
//			_, err = io.Copy(fd, reader)
//			if err != nil {
//				return err
//			}
//			reader.Close()
//		}
//	}
//	return nil
//}
